package mod_sensors;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.Null;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.CommunityTarget;



public class SNMPStyle {
	
	public String GetInformation() throws IOException{
		List<String> oidList = new ArrayList<String>();
		oidList.add(".1.3.6.1.4.1.34672.1.0");
		snmpGet("192.168.0.30", "public", oidList);
		return null;
	}
	public void test(){
		try{
			TransportMapping transport = new DefaultUdpTransportMapping(new UdpAddress("192.168.0.30/162"));
		
			Snmp snmp = new Snmp(transport);
			
			CommandResponder trapPrinter = new CommandResponder(){
				public synchronized void processPdu(CommandResponderEvent e){
					PDU command = e.getPDU();
					if (command != null){
						System.out.println(command.toString());
						
						//sendmesg(command.toString());
					}
				}
			};
			snmp.addCommandResponder(trapPrinter);
			System.out.println("start listening!\n");
			
			transport.listen();
			System.out.println(transport.isListening());
			
			Thread.sleep(180000);
			
		} catch (Exception e2){
			System.out.println(e2);
		}
	}
	
	private String protocol = "udp";
	private int port = 161;
	public void snmpGet(String ip, String community, List<String> oidList) throws IOException{
		CommunityTarget target = createDefault(ip, community);
		
		Snmp snmp = null;
		try{
			PDU pdu = new PDU();
			for (String oid : oidList){
				pdu.add(new VariableBinding(new OID(oid)));				
			}
			DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
			snmp = new Snmp(transport);
			snmp.listen();
			pdu.setType(PDU.GET);
			ResponseEvent respEvent = snmp.send(pdu, target);
			
			PDU response = respEvent.getResponse();
			if (response == null){
				System.out.println("response is null, request time out!\n");
			} else {
				for (int i = 0; i < response.size(); i++){
					VariableBinding vb = response.get(i);
					System.out.println(vb.getOid() + " = " + vb.getVariable());
				}
			} 
		}catch (Exception e){
			
		} finally{
			if (snmp != null){
				try{
					snmp.close();
				} catch( IOException ex1){
					snmp = null;
				}
			}
		}
		
	}
	
	public void snmpAsynGet(String ip, String community, List<String> oidList){
		CommunityTarget target = createDefault(ip, community);
		Snmp snmp = null;
		
		try{
			PDU pdu = new PDU();
			for (String oid : oidList){
				pdu.add(new VariableBinding(new OID(oid)));
			}
			final CountDownLatch latch = new CountDownLatch(1);
			
			ResponseListener listener = new ResponseListener(){
				public void onResponse(ResponseEvent event){
					((Snmp)event.getSource()).cancel(event.getRequest(), this);
					PDU response = event.getResponse();
					PDU request = event.getRequest();
					if (response == null){
						System.out.println("[ERROR]: response is null");
					} else if (response.getErrorStatus() != 0){
						System.out.println("[ERROR]: response status"
								+ response.getErrorStatus() + " Text:"
								+ response.getErrorStatusText());
					} else {
						System.out.println("Received response Success!");
						for (int i = 0; i < response.size(); i++){
							VariableBinding vb = response.get(i);
							System.out.println(vb.getOid() + " = " 
									+ vb.getVariable());
						}
						System.out.println("SNMP Asyn GetList OID finished. ");
						latch.countDown();
					}
				}
			};
			pdu.setType(PDU.GET);
			snmp.send(pdu, target, null, listener);
			System.out.println("asyn send pdu wait for response...");
			
			boolean wait = latch.await(30, TimeUnit.SECONDS);
			System.out.println("latch.await =:" + wait);
			snmp.close();
		} catch (Exception e){
			e.printStackTrace();
			System.out.println("SNMP Asyn GetList Exception:" + e);
		} 
	}
	public void snmpWalk(String ip, String community, String targetOid){
		CommunityTarget target = createDefault(ip, community);
		Snmp snmp = null;
		DefaultUdpTransportMapping transport = null;
		try{
			PDU requestPDU = new PDU();
			OID targetOID = new OID(targetOid);
			requestPDU.add(new VariableBinding(targetOID));
			requestPDU.setType(PDU.GETNEXT);
			
			transport = new DefaultUdpTransportMapping();
			snmp = new Snmp(transport);
			transport.listen();
			
			boolean finished = false;
			while (!finished){
				VariableBinding vb = null;
				ResponseEvent response = snmp.send(requestPDU, target);
				PDU responsePDU = response.getResponse();
				if (null == responsePDU){
					System.out.println("pdu == null\n");
					finished = true;
					break;
				} else {
					vb = responsePDU.get(0);
				}
				
				finished = checkWalkFinished(targetOID, responsePDU, vb);
				if (!finished){
					 System.out.println("----"+vb.toString());  
	                 System.out.println("----"+vb.getOid().toString());  
	                 System.out.println("----"+vb.getVariable().toString());
	                 
	                 requestPDU.setRequestID(new Integer32(0));
	                 requestPDU.set(0, vb);
				}
				
			}
			System.out.println("success finish snmp walk!\n");
		} catch (Exception e){
			System.out.println("SNMP walk Exception " + e);
		} finally{
			if (snmp != null){
				try{
					snmp.close();
				} catch (IOException ex1){
					snmp = null;
				}
			}
			if (transport != null){
				try{
					transport.close();
				} catch (IOException ex2){
					transport = null;
				}
			}
		}
	}
	
	private CommunityTarget createDefault(String ip, String community){
		Address address = GenericAddress.parse(protocol + ":" + ip + "/" + port);
		CommunityTarget target = new CommunityTarget();
		target.setCommunity(new OctetString(community));
		target.setAddress(address);
		target.setVersion(SnmpConstants.version1);
		target.setTimeout(3 * 1000L);
		target.setRetries(3);
		
		return target;
	}
	
	private boolean checkWalkFinished(OID targetOID, PDU responsePDU, VariableBinding vb){
		boolean finished = false;
		if (0 != responsePDU.getErrorStatus()){
			finished = true;
		} else if ( vb.getOid() == null){
			finished = true;
		} else if (vb.getOid().size() < targetOID.size()){
			finished = true;
		} else if (0 != targetOID.leftMostCompare(targetOID.size(), vb.getOid())){
			finished = true;
		} else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())){
			finished = true;
		} else if (0 >= vb.getOid().compareTo(targetOID)){
			finished = true;
		}
		return finished;
	}
}
